package services

import (
	admindao "TaskAssignmentSystem/internal/admin/dao"
	"TaskAssignmentSystem/internal/pkg/code"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"time"
)

const (
	tempSalary = "工资计算中"
)

type SalaryService struct {
}

func (s *SalaryService) UserSalaryExeclImport(viewUserSalarys []*admindao.SystemViewUserSalary, fileName string) error {
	fmt.Printf("UserSalaryExeclImport excel num: %d\n", len(viewUserSalarys))

	var serveFile admindao.Common[admindao.SystemUserSalaryFile]
	salaryFile := admindao.SystemUserSalaryFile{}
	salaryFile.FileTitle = fileName
	salaryFile.UserStatus = 0
	salaryFile.TeamStatus = 0
	serveFile.CreateOneReturnId(&salaryFile)

	var serve admindao.Common[admindao.SystemViewUserSalary]
	//清理临时表
	//serve.Truncate("tas_system_view_user_salary")
	//serve.Truncate("tas_system_view_team_user_salary")
	temp := admindao.SystemViewUserSalary{}
	temp.SalaryFileId = salaryFile.Id
	temp.UserId = tempSalary
	temp.RealName = tempSalary
	temp.NickName = tempSalary
	temp.ProjectId = tempSalary
	temp.Title = tempSalary
	temp.Remarks = tempSalary
	//进行中提示
	serve.CreateOne(temp)
	//验证团队功能是否开启
	var teamServe TeamService
	//teamOpen := teamServe.VerifyTeamALL()
	//团长缓存
	teamMap := map[string]*SystemViewUser{}
	teamMap["zxz"] = &SystemViewUser{}
	//用户
	for _, salary := range viewUserSalarys {
		//查团队编号
		salary.SalaryFileId = salaryFile.Id
		user, err := s.GetViewUserOne(salary.UserId)
		if err == nil {
			salary.RealName = user.RealName
			salary.NickName = user.NickName
			//查团长
			if _, ok := teamMap[user.TeamNumber]; !ok {
				res, err := teamServe.GetTeamOne(user.TeamNumber)
				if err != nil {
					teamMap[user.TeamNumber] = &SystemViewUser{}
				} else {
					teamUser, teamErr := s.GetViewUserOne(res.UserId)
					if teamErr == nil {
						//团队等级赋值
						//teamUser.Level = res.Level
						teamUser.TeamStatus = res.Status
						teamMap[user.TeamNumber] = &teamUser
					}
				}
			}

			tUser, _ := teamMap[user.TeamNumber]
			if tUser != nil {
				salary.TeamUserId = tUser.UserId
				salary.TeamRealName = tUser.RealName
				salary.TeamNickName = tUser.NickName
				salary.TeamNumber = user.TeamNumber
				salary.Level = tUser.Level
				salary.TeamPhone = tUser.Phone
				salary.TeamEmail = tUser.Email
				salary.TeamStatus = tUser.TeamStatus
				salary.TeamUserStatus = tUser.Status
			}
			/* 团长工资，改成用户工资发放后计算
			//工资计算前置条件
			if teamOpen && //1。团队功能开启,
				user.TeamNumber != "zxz" && //2。当前用户不属于zxz团队
				salary.ProjectId != "" && //3。项目不为空
				salary.IsTeamSalary == 1 && //4。团长奖励设置发放
				tUser.TeamStatus == 1 && //5。团长在职
				tUser.Status == 1 { //6。团长用户正常
				//团长工资核算,查询项目设置表
				if teamIncomes, err := teamServe.QueryTeamIncomeSettingByProjectIdAndLevel(salary.ProjectId, salary.Level); err == nil {
					for _, income := range teamIncomes {
						// 类型1：奖励表D列 * 团队等级比例
						if income.IncomeType == 1 {
							salary.TeamSalary += salary.BaseSalary * income.IncomeNumber
						}
						// 类型2：奖励表K列 * 团队等级数值
						if income.IncomeType == 2 {
							salary.TeamSalary += salary.TeamIncentiveSalary * income.IncomeNumber
						}
					}
				}
				salary.TeamBalance = salary.TeamSalary * 100
			}

			*/
		} else {
			salary.RealName = "(未查到此用户)"
			salary.NickName = "(未查到此用户)"
		}

	}
	serve.DeleteByIntColumn("salary_file_id", salaryFile.Id)
	//开始插入
	//serve.Truncate("tas_system_view_user_salary")
	pageSize := 1000
	//小于1000条直接新增
	if len(viewUserSalarys) < pageSize {
		serve.CreateT(viewUserSalarys)
	} else { //大于1000条分批新增
		teamLength := len(viewUserSalarys) / pageSize
		for i := 0; i < teamLength; i++ {
			slice := viewUserSalarys[i*pageSize : (i*pageSize)+pageSize]
			serve.CreateT(slice)
		}
		//剩余条数
		if len(viewUserSalarys)-(teamLength*pageSize) > 0 {
			slice := viewUserSalarys[teamLength*pageSize:]
			serve.CreateT(slice)
		}
	}
	return nil
	/*
		//聚合团长工资
		sql := "INSERT INTO tas_system_view_team_user_salary" +
			" (created_at,updated_at,team_user_id,team_real_name,team_nick_name,team_salary,team_balance,team_number,`level`,team_phone,team_email,team_remarks)" +
			" SELECT NOW(),NOW(),max(team_user_id),max(team_real_name),max(team_nick_name),sum(team_salary),sum(team_balance),max(team_number),max(`level`)," +
			"max(`team_phone`),max(`team_email`),max(`team_remarks`) FROM tas_system_view_user_salary WHERE team_user_id != '' GROUP BY team_user_id"
		return serve.ExecSql(sql).Error
	*/
}

func (s *SalaryService) SalaryUserPlaceOnFile(fileId uint) error {
	var serveFile CommonService[admindao.SystemUserSalaryFile]
	serveFile.Query = map[string]interface{}{"id": fileId}
	if file, err := serveFile.First(); err != nil {
		return errors.New("没有找到对于的上传文件记录！")
	} else {
		if file.UserStatus != 0 {
			return errors.New("用户工资已经发放完毕，不能重复发放！")
		}
	}
	var teamServe TeamService
	teamOpen := teamServe.VerifyTeamALL()
	teamMap := map[string]int64{}
	var serve admindao.Common[admindao.SystemViewUserSalary]
	/*
		//用户工资备案
		sqlUserSalary :=
			"INSERT INTO tas_system_user_salary (`created_at`,`updated_at`,`user_id`,`real_name`,`nick_name`,`base_salary`," +
				"`incentive_salary`,`sum_salary`,`balance`,`project_id`,`title`,`remarks`,`is_team_salary`,`team_remarks`,`team_user_id`,`team_real_name`," +
				"`team_nick_name`,`team_salary`,`team_balance`,`team_number`,`level`,`team_phone`,`team_email`" +
				") SELECT `created_at`,`updated_at`,`user_id`,`real_name`,`nick_name`,`base_salary`," +
				"`incentive_salary`,`sum_salary`,`balance`,`project_id`,`title`,`remarks`,`is_team_salary`,`team_remarks`,`team_user_id`,`team_real_name`," +
				"`team_nick_name`,`team_salary`,`team_balance`,`team_number`,`level`,`team_phone`,`team_email` FROM tas_system_view_user_salary"
		serve.ExecSql(sqlUserSalary)

	*/
	//serve.CustomWhere = append(serve.CustomWhere, fmt.Sprintf("team_number != ''"))
	serve.Query = map[string]interface{}{"salary_file_id": fileId}
	if userSalarys, err := serve.FindAll(serve.Query); err == nil {
		var userBalanceLogService UserBalanceLogService
		//第一次循环发用户工资,确保团队等级计算完成
		for _, salary := range userSalarys {
			userBalanceLogService.AddPayWagesLog(salary.UserId, salary.Remarks, salary.DetailUrl, salary.Balance, 3)
		}
		//第二次循环计算团长工资
		for _, salary := range userSalarys {
			//算团长工资，工资计算前置条件
			if teamOpen && //1。团队功能开启,
				salary.TeamNumber != "zxz" && //2。当前用户不属于zxz团队
				salary.ProjectId != "" && //3。项目不为空
				salary.IsTeamSalary == 1 && //4。团长奖励设置发放
				salary.TeamStatus == 1 && //5。团长在职
				salary.TeamUserStatus == 1 { //6。团长用户正常
				//查询团队等级
				if _, ok := teamMap[salary.TeamNumber]; !ok {
					salary.Level = teamServe.TeamMaxLevel(salary.TeamNumber)
					teamMap[salary.TeamNumber] = salary.Level
				} else {
					salary.Level = teamMap[salary.TeamNumber]
				}
				//团长工资核算,查询项目设置表
				if teamIncomes, err := teamServe.QueryTeamIncomeSettingByProjectIdAndLevel(salary.ProjectId, salary.Level); err == nil {
					for _, income := range teamIncomes {
						// 类型1：奖励表D列 * 团队等级比例
						if income.IncomeType == 1 {
							salary.TeamSalary += salary.BaseSalary * income.IncomeNumber
						}
						// 类型2：奖励表K列 * 团队等级数值
						if income.IncomeType == 2 {
							salary.TeamSalary += salary.TeamIncentiveSalary * income.IncomeNumber
						}
					}
				}
				salary.TeamBalance = salary.TeamSalary * 100
				serve.UpdateOne(salary.Id, map[string]interface{}{"team_salary": salary.TeamSalary, "team_balance": salary.TeamBalance, "Level": salary.Level})
			}
		}
	}
	//用户发放时间
	serve.Update(map[string]interface{}{
		"user_grant_time": time.Now()})

	return serveFile.Update(map[string]interface{}{
		"user_status": 1})

	//清理缓存表
	//serve.Truncate("tas_system_view_user_salary")
}

func (s *SalaryService) SalaryUserPlaceOnFileReturn(fileId uint) error {
	var serveFile CommonService[admindao.SystemUserSalaryFile]
	serveFile.Query = map[string]interface{}{"id": fileId}
	if file, err := serveFile.First(); err != nil {
		return errors.New("没有找到对于的上传文件记录！")
	} else {
		if file.UserStatus != 1 {
			return errors.New("用户工资未发放或已退回，无法继续操作！")
		}
	}
	var serve admindao.Common[admindao.SystemViewUserSalary]
	serve.CustomWhere = append(serve.CustomWhere, fmt.Sprintf("team_number != ''"))
	serve.Query = map[string]interface{}{"salary_file_id": fileId}
	if userSalarys, err := serve.FindAll(serve.Query); err == nil {
		var userBalanceLogService UserBalanceLogService
		for _, salary := range userSalarys {
			userBalanceLogService.RetrunPayWagesLog(salary.UserId, "收入撤回，详情请联系平台运营", salary.Balance, 3)
		}
	}
	//用户发放时间
	serve.Update(map[string]interface{}{
		"user_withdraw_time": time.Now()})

	return serveFile.Update(map[string]interface{}{
		"user_status": 2})
}

func (s *SalaryService) SalaryTeamUserPlaceOnFile(fileId uint) error {
	var serveFile CommonService[admindao.SystemUserSalaryFile]
	serveFile.Query = map[string]interface{}{"id": fileId}
	if file, err := serveFile.First(); err != nil {
		return errors.New("没有找到对于的上传文件记录！")
	} else {
		if file.UserStatus != 1 {
			return errors.New("用户工资发放完成后，才可发团长工资！")
		}
		if file.TeamStatus == 1 {
			return errors.New("团长工资已经发放完毕，不能重复发放！")
		}
	}
	var serve admindao.Common[admindao.SystemViewTeamUserSalary]
	//清理团长工资临时表
	serve.Truncate("tas_system_view_team_user_salary")
	/*
		//团长工资提成备案
		sqlTeamUserSalary :=
			"INSERT INTO tas_system_team_user_salary (`created_at`,`updated_at`,`team_real_name`,`team_nick_name`," +
				"`team_salary`,`team_balance`,`team_number`,`level`,`team_phone`,`team_email`,`team_remarks`" +
				") SELECT `created_at`,`updated_at`,`team_real_name`,`team_nick_name`,`team_salary`," +
				"`team_balance`,`team_number`,`level`,`team_phone`,`team_email`,`team_remarks` FROM tas_system_view_team_user_salary"
		serve.ExecSql(sqlTeamUserSalary)
	*/

	//聚合团长工资
	sql := "INSERT INTO tas_system_view_team_user_salary" +
		" (created_at,updated_at,team_user_id,team_real_name,team_nick_name,team_salary,team_balance,team_number,`level`,team_phone,team_email,team_remarks,detail_url_tl)" +
		" SELECT NOW(),NOW(),max(team_user_id),max(team_real_name),max(team_nick_name),sum(team_salary),sum(team_balance),max(team_number),max(`level`)," +
		"max(`team_phone`),max(`team_email`),max(`team_remarks`),max(`detail_url_tl`) FROM tas_system_view_user_salary WHERE team_user_id != '' and salary_file_id = " + fmt.Sprintf("%d", fileId) +
		" GROUP BY team_user_id"
	serve.ExecSql(sql)

	//query := map[string]interface{}{"salary_file_id": fileId}
	if userTeamSalarys, err := serve.FindAll(nil); err == nil {
		var userBalanceLogService UserBalanceLogService
		for _, salary := range userTeamSalarys {
			userBalanceLogService.AddPayWagesLog(salary.TeamUserId, salary.TeamRemarks, salary.DetailUrlTl, salary.TeamBalance, 4)
		}
	}
	var serveTeam admindao.Common[admindao.SystemViewUserSalary]
	serveTeam.Query = map[string]interface{}{"salary_file_id": fileId}
	//团长发放时间
	serveTeam.Update(map[string]interface{}{
		"team_grant_time": time.Now()})
	return serveFile.Update(map[string]interface{}{
		"team_status": 1})
}

func (s *SalaryService) SalaryTeamUserPlaceOnFileReturn(fileId uint) error {
	var serveFile CommonService[admindao.SystemUserSalaryFile]
	serveFile.Query = map[string]interface{}{"id": fileId}
	if file, err := serveFile.First(); err != nil {
		return errors.New("没有找到对于的上传文件记录！")
	} else {
		if file.TeamStatus != 1 {
			return errors.New("团长工资未发放或已退回，无法继续操作！")
		}
	}
	var serve admindao.Common[admindao.SystemViewTeamUserSalary]
	//清理团长工资临时表
	serve.Truncate("tas_system_view_team_user_salary")
	//聚合团长工资
	sql := "INSERT INTO tas_system_view_team_user_salary" +
		" (created_at,updated_at,team_user_id,team_real_name,team_nick_name,team_salary,team_balance,team_number,`level`,team_phone,team_email,team_remarks)" +
		" SELECT NOW(),NOW(),max(team_user_id),max(team_real_name),max(team_nick_name),sum(team_salary),sum(team_balance),max(team_number),max(`level`)," +
		"max(`team_phone`),max(`team_email`),max(`team_remarks`) FROM tas_system_view_user_salary WHERE team_user_id != '' and salary_file_id = " + fmt.Sprintf("%d", fileId) +
		" GROUP BY team_user_id"
	serve.ExecSql(sql)
	//query := map[string]interface{}{"salary_file_id": fileId}
	if userTeamSalarys, err := serve.FindAll(nil); err == nil {
		var userBalanceLogService UserBalanceLogService
		for _, salary := range userTeamSalarys {
			userBalanceLogService.RetrunPayWagesLog(salary.TeamUserId, "团长工资撤回", salary.TeamBalance, 4)
		}
	}
	var serveTeam admindao.Common[admindao.SystemViewUserSalary]
	serveTeam.Query = map[string]interface{}{"salary_file_id": fileId}
	//团长撤回时间
	serveTeam.Update(map[string]interface{}{
		"team_withdraw_time": time.Now()})
	return serveFile.Update(map[string]interface{}{
		"team_status": 2})
}

func (s *SalaryService) QueryUserSalaryFile(page, pageSize int64, param map[string]interface{}) (int64, []admindao.SystemUserSalaryFile, error) {
	var serve CommonService[admindao.SystemUserSalaryFile]
	serve.Page = page
	serve.PageSize = pageSize
	serve.Order = "id desc"
	if _, exist := param["upload_time_start"]; exist {
		serve.WhereStr = append(serve.WhereStr, fmt.Sprintf("created_at >= '%v' ", param["upload_time_start"]))
	}
	if _, exist := param["upload_time_end"]; exist {
		serve.WhereStr = append(serve.WhereStr, fmt.Sprintf("created_at <= '%v' ", param["upload_time_end"]))
	}
	if _, exist := param["file_title"]; exist {
		serve.WhereStr = append(serve.WhereStr, fmt.Sprintf("file_title like '%%%v%%'", param["file_title"]))
	}
	if tisList, err := serve.SelectList(); err != nil {
		return 0, nil, err
	} else {
		return tisList.Total, tisList.Data, nil
	}
}
func (s *SalaryService) QueryUserSalary(fileId uint, page, pageSize int64) (int64, []admindao.SystemViewUserSalary, error) {
	var serve CommonService[admindao.SystemViewUserSalary]
	serve.Page = page
	serve.PageSize = pageSize
	serve.Query = map[string]interface{}{"salary_file_id": fileId}

	if tisList, err := serve.SelectList(); err != nil {
		return 0, nil, err
	} else {
		return tisList.Total, tisList.Data, nil
	}
}

/*
	func (s *SalaryService) QueryTeamUserSalary(userId string, page, pageSize int64) (int64, []admindao.SystemViewTeamUserSalary, error) {
		var serve CommonService[admindao.SystemViewTeamUserSalary]
		serve.Page = page
		serve.PageSize = pageSize
		if userId != "" {
			serve.Query = map[string]interface{}{"team_user_id": userId}
		}
		if tisList, err := serve.SelectList(); err != nil {
			return 0, nil, err
		} else {
			return tisList.Total, tisList.Data, nil
		}
	}

	func (s *SalaryService) QueryUserSalaryPlaceOnFile(userId string, page, pageSize int64) (int64, []admindao.SystemViewUserSalary, error) {
		var serve CommonService[admindao.SystemViewUserSalary]
		serve.Page = page
		serve.PageSize = pageSize
		if userId != "" {
			serve.Query = map[string]interface{}{"user_id": userId}
		}
		if tisList, err := serve.SelectList(); err != nil {
			return 0, nil, err
		} else {
			return tisList.Total, tisList.Data, nil
		}
	}

	func (s *SalaryService) QueryTeamUserSalaryPlaceOnFile(userId string, page, pageSize int64) (int64, []admindao.SystemViewTeamUserSalary, error) {
		var serve CommonService[admindao.SystemViewTeamUserSalary]
		serve.Page = page
		serve.PageSize = pageSize
		if userId != "" {
			serve.Query = map[string]interface{}{"team_user_id": userId}
		}
		if tisList, err := serve.SelectList(); err != nil {
			return 0, nil, err
		} else {
			return tisList.Total, tisList.Data, nil
		}
	}
*/
func (s *SalaryService) GetViewUserOne(userId string) (SystemViewUser, error) {
	var userServe CommonService[SystemViewUser]
	userServe.Query = map[string]interface{}{"user_id": userId}
	return userServe.First()
}

func (s *SalaryService) AddBalance(user SystemViewUser, balance float64) {
	var userServe CommonService[SystemViewUser]
	userServe.Query = map[string]interface{}{"user_id": user.UserId}
	var teamServe TeamService
	userServe.Update(map[string]interface{}{
		"balance": gorm.Expr("`balance` + ?", int64(balance))})
	teamServe.DoEffectiveManpower(user.Id, user.UserId, user.TeamNumber, user.IsEffectiveManpower, user.IsAuthentication, user.Balance+balance)
}

func (s *SalaryService) DelBalance(userId string, balance float64) (SystemViewUser, error) {
	var userServe CommonService[SystemViewUser]
	userServe.Query = map[string]interface{}{"user_id": userId}
	userServe.Update(map[string]interface{}{
		"balance": gorm.Expr("`balance` - ?", balance)})
	return userServe.First()
}

func (SystemViewUser) TableName() string {
	return "tas_system_user"
}

type SystemViewUser struct {
	code.Model
	TeamNumber          string  `json:"team_number"`                //团队编号
	UserNumber          string  `json:"user_number"`                //用户编号
	UserId              string  `json:"user_id" gorm:"uniqueIndex"` //用户Id
	RealName            string  `json:"real_name"`                  //姓名
	Phone               string  `json:"phone" gorm:"uniqueIndex"`   //手机号
	Email               string  `json:"email"`                      //邮箱
	NickName            string  `json:"nick_name"`                  //昵称
	Status              int     `json:"status"`                     //0 注销;1 正常; 2 封禁
	Balance             float64 `json:"balance"`                    //用户芝草余额
	IsAuthentication    int     `json:"is_authentication"`          //是否实名认证，0 未认证;1 已认证;
	IsEffectiveManpower int     `json:"is_effective_manpower"`      //是否有效人力，0 否;1 是;
	Level               int64   `json:"level" gorm:"-"`             //团队等级
	TeamStatus          int     `json:"team_status" gorm:"-"`       //0 注销;1 任职中; 2 已离职
	DetailUrl           string  `json:"detail_url"`                 //详情链接
}

/*func (s *SalaryService) DeleteUserSalary(id uint) error {
	var serveFile CommonService[admindao.SystemUserSalaryFile]
	serveFile.Query = map[string]interface{}{"id": id}
	if _, err := serveFile.First(); err != nil {
		return errors.New("没有找到对于的上传文件记录！")
	}

	var serve admindao.Common[admindao.SystemViewUserSalary]
	serve.Query = map[string]interface{}{"salary_file_id": id}
	if err := serve.RemoveUnscopedWhere(serve.Query).Error; err != nil {
		return err
	} else {
		return
	}

	topicConfigurationServe.Query = map[string]interface{}{"id": RequestParams.Id}
	if err := topicConfigurationServe.RemoveUnscopedWhere(topicConfigurationServe.Query).Error; err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.StatusText(iris.StatusOK)})
		return
	}
}*/
